package com.cygsunri.event.dao;

import com.cygsunri.event.entity.EventInfo;
import com.cygsunri.event.entity.EventParams;
import com.cygsunri.history.config.InfluxDBConfig;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

@Repository
public class EventDao {

    @Value("${spring.influxDB.name}")
    private String influxDBName;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private InfluxDBConfig influxDBConfig;

    private InfluxDB influxDB;

    @PostConstruct
    public void EventDaoInit() {
        influxDB = influxDBConfig.getInfluxDB();
    }

    /**
     * 遥信参数表信息映射为EventInfo类
     */
    public List<EventInfo> getYxInfo() {
        final List<EventInfo> eventInfoList = new ArrayList<>();
        String sql = "SELECT a.代码 AS 测点代码,a.描述 AS 测点描述 ,b.代码 AS 设备代码,b.描述 AS 设备描述,c.代码 AS 站点代码,c.描述 " +
                "AS 站点描述 FROM 遥信参数表 a,scd设备参数表 b ,(SELECT a.belong AS 代码,a.PsrID,b.描述 AS 描述 FROM " +
                "tb_psrtemplatemapping a,scd设备参数表 b WHERE a.belong=b.代码) c WHERE a.`设备代码` = b.`代码`  " +
                "AND c.PsrID =b.`代码` ";

        try {
            jdbcTemplate.query(sql, new RowCallbackHandler() {
                public void processRow(ResultSet resultSet) throws SQLException {
                    eventInfoList.add(new EventInfo(resultSet.getString("测点代码").trim(),
                            resultSet.getString("测点描述").trim(),
                            resultSet.getString("设备代码").trim(),
                            resultSet.getString("设备描述").trim(),
                            resultSet.getString("站点代码").trim(),
                            resultSet.getString("站点描述").trim()));
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }

        return eventInfoList;
    }

    /**
     * 按条件读取EventInfoList
     *
     * @return infoList
     */
    public List<EventInfo> getEventInfoList(EventParams eventParams) {
        String zoneStr = TimeZone.getDefault().getID();
        String startDate = eventParams.getStartDate() + " 00:00:00";
        String endDate = eventParams.getEndDate() + " 23:59:59";
        String sql = String.format("select * from processedEvent WHERE time >='%s' and time <= '%s'", startDate, endDate);

        if (!eventParams.getConfirm().toLowerCase().equals("all")) {
            sql = sql + " and confirm = " + Boolean.parseBoolean(eventParams.getConfirm());
        }

        if (!eventParams.getEventType().toLowerCase().equals("all")) {
            sql = sql + " and type = " + eventParams.getEventType();
        }

        if (eventParams.getSearchName()!=null && !eventParams.getSearchName().equals("")) {
            sql = sql + " and (txt =~ /" + eventParams.getSearchName() + "/ or deviceDesc =~ /" + eventParams.getSearchName() + "/) ";
        }
        sql = sql + " ORDER BY time DESC tz('" + zoneStr + "')";
        final Query q = new Query(sql);
        QueryResult queryResult = influxDB.query(q);
        EventInfluxMapper influxMapper = new EventInfluxMapper();
        return influxMapper.toEventInfo(queryResult);
    }

    /**
     * 存储单个事件到influxDB
     */
    public void insertEvent(EventInfo eventInfo, Boolean confirm) {
        if (eventInfo != null) {
            influxDB.write(Point.measurement("processedEvent")
                    .time(eventInfo.getTimeStamp(), TimeUnit.MILLISECONDS)
                    .tag("measurementId", eventInfo.getMeasurementID())
                    .addField("uuid", eventInfo.getId())
                    .addField("substationId", eventInfo.getSubstationID())
                    .addField("substationDesc", eventInfo.getSubstationDesc())
                    .addField("deviceId", eventInfo.getPsrId())
                    .addField("deviceDesc", eventInfo.getPsrDesc())
                    .addField("measurementDesc", eventInfo.getMeasurementDesc())
                    .addField("txt", eventInfo.getTxtInfo())
                    .addField("type", eventInfo.getType())
                    .addField("confirm", confirm)
                    .build());
        }
    }

    /**
     * 存储未确认事件List到influxDB
     */
    public void insertEventList(List<EventInfo> eventInfoList) {
        //eventInfoList.forEach(eventInfo -> insertEvent(eventInfo, false));
        BatchPoints batchPoints = BatchPoints
                .database(influxDBName)
                .consistency(InfluxDB.ConsistencyLevel.ALL)
                .build();

        eventInfoList.forEach(eventInfo -> {

            Point point = Point.measurement("processedEvent")
                    .time(eventInfo.getTimeStamp(), TimeUnit.MILLISECONDS)
                    .tag("measurementId", eventInfo.getMeasurementID())
                    .addField("uuid", eventInfo.getId())
                    .addField("substationId", eventInfo.getSubstationID())
                    .addField("substationDesc", eventInfo.getSubstationDesc())
                    .addField("deviceId", eventInfo.getPsrId())
                    .addField("deviceDesc", eventInfo.getPsrDesc())
                    .addField("measurementDesc", eventInfo.getMeasurementDesc())
                    .addField("txt", eventInfo.getTxtInfo())
                    .addField("type", eventInfo.getType())
                    .addField("confirm", eventInfo.getIsConfirm())
                    .build();
            batchPoints.point(point);
        });
        influxDB.write(batchPoints);
    }

    /**
     * 前台确认事件List到influxDB
     */
    public void confirmEventList(List<EventInfo> eventInfoList) {
        //eventInfoList.forEach(eventInfo -> insertEvent(eventInfo, true));
        BatchPoints batchPoints = BatchPoints
                .database(influxDBName)
                .consistency(InfluxDB.ConsistencyLevel.ALL)
                .build();

        eventInfoList.forEach(eventInfo -> {

            Point point = Point.measurement("processedEvent")
                    .time(eventInfo.getTimeStamp(), TimeUnit.MILLISECONDS)
                    .tag("measurementId", eventInfo.getMeasurementID())
                    .addField("uuid", eventInfo.getId())
                    .addField("substationId", eventInfo.getSubstationID())
                    .addField("substationDesc", eventInfo.getSubstationDesc())
                    .addField("deviceId", eventInfo.getPsrId())
                    .addField("deviceDesc", eventInfo.getPsrDesc())
                    .addField("measurementDesc", eventInfo.getMeasurementDesc())
                    .addField("txt", eventInfo.getTxtInfo())
                    .addField("type", eventInfo.getType())
                    .addField("confirm", true)
                    .build();
            batchPoints.point(point);
        });
        influxDB.write(batchPoints);
    }
}
